package cn.wolfcode.wolf2w.redis.service.impl;

import cn.wolfcode.wolf2w.domain.Travel;
import cn.wolfcode.wolf2w.domain.TravelUserIdFavors;
import cn.wolfcode.wolf2w.domain.UserIdFavors;
import cn.wolfcode.wolf2w.redis.service.ITravelStatisVORedisService;
import cn.wolfcode.wolf2w.redis.service.ITravelStatisVORedisService;
import cn.wolfcode.wolf2w.redis.vo.TravelStatisVO;
import cn.wolfcode.wolf2w.service.ITravelService;
import cn.wolfcode.wolf2w.service.IUserIdFavorsService;
import cn.wolfcode.wolf2w.util.DateUtil;
import cn.wolfcode.wolf2w.util.RidesKey;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class TravelStatisVORedisServiceImpl implements ITravelStatisVORedisService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ITravelService travelService;
    @Autowired
    private IUserIdFavorsService userIdFavorsService;
    @Autowired
    private MongoTemplate template;

    @Override
    public void viewnumIncrease(String tid, int num){
        TravelStatisVO vo = getTravelStatisVO(tid);
        vo.setViewnum(vo.getViewnum() + num);
        this.setTravelStatisVO(vo);
    }


    public TravelStatisVO getTravelStatisVO(String tid){
        String join = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join(tid);

        TravelStatisVO vo = null;

        if (!redisTemplate.hasKey(join)){

            vo = new TravelStatisVO();

            Travel travel = travelService.findById(tid);
            BeanUtils.copyProperties(travel,vo);
            vo.setTravelId(travel.getId());

        }else {
            String travelStatisVO = redisTemplate.opsForValue().get(join);
            vo = JSON.parseObject(travelStatisVO, TravelStatisVO.class);
        }
        return vo;
    }

    @Override
    public void setTravelStatisVO(TravelStatisVO vo){
        String key = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join(vo.getTravelId());
        redisTemplate.opsForValue().set(key, JSON.toJSONString(vo));
    }

    @Override
    public boolean isTravelVoExist(String id) {
        String key = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join(id);
        if (redisTemplate.hasKey(key)){
            return true;
        }
        return false;
    }

    @Override
    public List<TravelStatisVO> findAllTravelStatisVO() {
        String patten = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join("*");
        ArrayList<TravelStatisVO> vos = new ArrayList<>();
        Set<String> keys = redisTemplate.keys(patten);
        if (keys != null && keys.size() > 0){
            for (String key : keys) {
                String vo = redisTemplate.opsForValue().get(key);
                vos.add(JSON.parseObject(vo,TravelStatisVO.class));
            }
        }
        return vos;
    }

    @Override
    public void setMongodb(List<TravelStatisVO> travelStatisVOS) {
        for (TravelStatisVO travelStatisVO : travelStatisVOS) {
            /*Travel travel = travelService.findById(travelStatisVO.getTravelId());
            travel.setViewnum(travelStatisVO.getViewnum());
            travel.setReplynum(travelStatisVO.getReplynum());
            travel.setSharenum(travelStatisVO.getSharenum());
            travel.setThumbsupnum(travelStatisVO.getThumbsupnum());
            travel.setFavornum(travelStatisVO.getFavornum());
            travelService.update(travel);*/

            Query query = new Query();
            query.addCriteria(Criteria.where("_id").is(travelStatisVO.getTravelId()));

            Update update = new Update();
            update.set("viewnum", travelStatisVO.getViewnum());
            update.set("replynum",travelStatisVO.getReplynum() );
            update.set("sharenum", travelStatisVO.getSharenum());
            update.set("thumbsupnum", travelStatisVO.getThumbsupnum());
            update.set("favornum", travelStatisVO.getFavornum());

            template.updateMulti(query,update ,Travel.class );
        }
    }


    @Override
    public TravelStatisVO statisVo(String tid) {

       /* String join = RedisKeys.TRAVEL_STATIS_TRAVELSTATISVO.join(tid);
        String stategyStatisVo = redisTemplate.opsForValue().get(join);


        if (!StringUtils.hasLength(stategyStatisVo)){

            TravelStatisVO travelStatisVO = new TravelStatisVO();
            Travel travel = travelService.findById(tid);
            BeanUtils.copyProperties(travel,travelStatisVO);
            travelStatisVO.setViewnum(travelStatisVO.getViewnum() + 1);
            redisTemplate.opsForValue().set(join, JSON.toJSONString(travelStatisVO), Consts.VERIFY_CODE_VAI_TIME*60L, TimeUnit.SECONDS);

            return travelStatisVO;
        }else {
            TravelStatisVO travelStatisVO = JSON.parseObject(stategyStatisVo, TravelStatisVO.class);
            travelStatisVO.setViewnum(travelStatisVO.getViewnum() + 1);
            redisTemplate.opsForValue().set(join, JSON.toJSONString(travelStatisVO), Consts.VERIFY_CODE_VAI_TIME*60L, TimeUnit.SECONDS);
            return travelStatisVO;
        }*/

        String join = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join(tid);

        TravelStatisVO vo = null;

        if (!redisTemplate.hasKey(join)){

            vo = new TravelStatisVO();

            Travel travel = travelService.findById(tid);
            BeanUtils.copyProperties(travel,vo);
            vo.setTravelId(travel.getId());

        }else {
            String travelStatisVO = redisTemplate.opsForValue().get(join);
            vo = JSON.parseObject(travelStatisVO, TravelStatisVO.class);
        }

        return vo;
    }

    @Override
    public void replynumIncrease(String travelId, int num) {
        TravelStatisVO vo = getTravelStatisVO(travelId);
        vo.setReplynum(vo.getReplynum() + num);
        this.setTravelStatisVO(vo);
    }

    @Override
    public boolean favor(String tid, String uid) {
        //先查询是否有当前这篇攻略的收藏的list集合(里面存放对应已经点赞的用户)
        String key = RidesKey.TRAVEL_USER_ID.join(uid);
        TravelStatisVO travelStatisVO = this.getTravelStatisVO(tid);



       UserIdFavors userIdFavors = new UserIdFavors();
        userIdFavors.setFavors(new ArrayList<>());

        if (redisTemplate.hasKey(key)){

            userIdFavors = JSON.parseObject(redisTemplate.opsForValue().get(key), UserIdFavors.class);
            List<String> objects = userIdFavors.getFavors();
            if (objects.contains(tid)){
                objects.remove(tid);
                //把当前用户id移除出集合
                //对应点赞数-1
                travelStatisVO.setFavornum(travelStatisVO.getFavornum() - 1);
                //把数据更新回去
                redisTemplate.opsForValue().set(key, JSON.toJSONString(userIdFavors));
                this.setTravelStatisVO(travelStatisVO);
                return false;
            }
            objects.add(tid);
            redisTemplate.opsForValue().set(key, JSON.toJSONString(userIdFavors));
            travelStatisVO.setFavornum(travelStatisVO.getFavornum() + 1);
            this.setTravelStatisVO(travelStatisVO);

           /* if (favors1.contains(tid)){
                favors1.remove(tid);
                //把当前用户id移除出集合
                //对应点赞数-1
                travelStatisVO.setFavornum(travelStatisVO.getFavornum() - 1);
                //把数据更新回去
                redisTemplate.opsForValue().set(key, JSON.toJSONString(favors1));
                this.setTravelStatisVO(travelStatisVO);
                return false;
            }else{
                favors1.add(tid);
                redisTemplate.opsForValue().set(key, JSON.toJSONString(favors1));
                travelStatisVO.setFavornum(travelStatisVO.getFavornum() + 1);
                this.setTravelStatisVO(travelStatisVO);
            }*/

        }else {

            UserIdFavors favors = userIdFavorsService.findByUsid(uid);
            List<String> favors1 = favors.getFavors();
            if (favors1.contains(tid)){
                favors1.remove(tid);
                //把当前用户id移除出集合
                //对应点赞数-1
                travelStatisVO.setFavornum(travelStatisVO.getFavornum() - 1);
                //把数据更新回去
                redisTemplate.opsForValue().set(key, JSON.toJSONString(favors));
                this.setTravelStatisVO(travelStatisVO);
                return false;
            }
            favors1.add(tid);
            redisTemplate.opsForValue().set(key, JSON.toJSONString(favors));
            travelStatisVO.setFavornum(travelStatisVO.getFavornum() + 1);
            this.setTravelStatisVO(travelStatisVO);
        }


        return true;
    }

    @Override
    public List<String> gettravelUserIds(String userId) {
        String key = RidesKey.TRAVEL_USER_ID.join(userId);
        TravelUserIdFavors userIdFavors = new TravelUserIdFavors();
        userIdFavors.setFavors(new ArrayList());
        if (redisTemplate.hasKey(key)){
            userIdFavors = JSON.parseObject(redisTemplate.opsForValue().get(key), TravelUserIdFavors.class);
        }
        return userIdFavors.getFavors();
    }

    @Override
    public boolean travelThumbup(String tid, String id) {
        String key = RidesKey.TRAVEL_THUMBUP.join(tid,id);
        if (redisTemplate.hasKey(key)){
            return false;
        }
        Date now = new Date();

        Date end = DateUtil.getEndDate(new Date());

        long dateBetween = DateUtil.getDateBetween(now, end);

        redisTemplate.opsForValue().set(key, tid, dateBetween, TimeUnit.SECONDS);

        String voKey = RidesKey.TRAVEL_STATIS_TRAVELSTATISVO.join(tid);

        TravelStatisVO travelStatisVO = this.getTravelStatisVO(tid);
        travelStatisVO.setThumbsupnum(travelStatisVO.getThumbsupnum() + 1);
        this.setTravelStatisVO(travelStatisVO);

        return true;
    }



}

